package com.miplus.ccrm.workflow.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.CmdResVo;
import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.JPubUtils;
import com.miplus.ccrm.common.ServiceException;
import com.miplus.ccrm.workflow.mapper.WorkflowMapper;
import com.miplus.ccrm.workflow.model.dto.workflow.*;
import com.miplus.ccrm.workflow.model.enums.WorkflowStatusEnum;
import com.miplus.ccrm.workflow.model.po.Workflow;
import com.miplus.ccrm.workflow.model.po.WorkflowVersion;
import com.miplus.ccrm.workflow.model.vo.WorkflowDetailsVO;
import com.miplus.ccrm.workflow.model.vo.WorkflowVO;
import com.miplus.ccrm.workflow.model.vo.WorkflowVersionVO;
import com.miplus.ccrm.workflow.service.WorkflowService;
import com.miplus.ccrm.workflow.service.WorkflowVersionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 工作流服务实现类
 */
@Slf4j
@Service
public class WorkflowServiceImpl extends MPJBaseServiceImpl<WorkflowMapper, Workflow> implements WorkflowService {



    @Resource
    private WorkflowVersionService workflowVersionService;

    @Override
    @Transactional
    public CmdResVo createWorkflow(WorkflowCreateDTO dto, String userId) {
        //需要优化，创建时候创建默认画布数据 todo
        Workflow workflow = new Workflow();
        workflow.setCreatedBy(userId);
        workflow.setVersion(1);
        BeanUtils.copyProperties(dto, workflow);
        int result = baseMapper.insert(workflow);
        //同时创建一个版本号，版本名字为当前时间，版本画布数据为空，版本流程配置为空
        //版本号从1开始，后续更新历史版本时，版本号递增
        WorkflowVersion workflowVersion = new WorkflowVersion();
        workflowVersion.setWorkflowId(workflow.getId());
        workflowVersion.setVersion(1);
        workflowVersion.setVersionName(new Date().toString());
        workflowVersion.setVersionDesc(dto.getDescription());
        workflowVersion.setCanvasData("{}");
        workflowVersion.setWorkflowConfig("{}");
        workflowVersion.setChangeLog("首次创建");
        workflowVersionService.save(workflowVersion);
        return new CmdResVo(result, workflow.getId());
    }


    @Override
    public CmdResVo updateWorkflow(WorkflowUpdateDTO dto, String userId) {
            Workflow workflow = baseMapper.selectById(dto.getId());
            //获取当前使用的版本号
             int currentVersion = workflow.getVersion();
            if (workflow == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value,EnumRCode.DataNotExist.name);
            }
            //如果更改画布的数据则会生成一个新版本，方便历史版本的切换
           if (dto.getCanvasData() != null) {
                //版本号递增,获取当前记录的最大版本递增值
               WorkflowVersion latestVersion = workflowVersionService.lambdaQuery()
                       .eq(WorkflowVersion::getWorkflowId, workflow.getId())
                       .orderByDesc(WorkflowVersion::getVersion)
                       .last("LIMIT 1")  // 限制只返回一条记录
                       .one();
               int version = (latestVersion != null ? latestVersion.getVersion() : 0) + 1;
                workflow.setVersion(version);
                //创建一个新的版本
                WorkflowVersion workflowVersion = new WorkflowVersion();
                workflowVersion.setWorkflowId(workflow.getId());
                workflowVersion.setVersion(version);
                workflowVersion.setVersionName(JPubUtils.DTimeToString(new Date()));
               workflowVersion.setVersionDesc(dto.getDescription());
                workflowVersion.setCanvasData(dto.getCanvasData());
                //其他有值则更新，没有还有之前的值
                workflowVersion.setWorkflowConfig(dto.getWorkflowConfig()!= null?dto.getWorkflowConfig():getWorkflowVersion(workflow.getId(), currentVersion).getWorkflowConfig());
                workflowVersion.setChangeLog("更新画布数据");
                workflowVersionService.save(workflowVersion);
                //设置当前话术为当前更改的版本
                workflow.setVersion(version);
           }
           //如果不更新画布数据则直接更新
            BeanUtils.copyProperties(dto, workflow);
            int result = baseMapper.updateById(workflow);
            return new CmdResVo(result, workflow.getId());
    }


    /**
     *  获取指定话术版本号的信息，一个方法
     * @return
     */
    private WorkflowVersion getWorkflowVersion(String workflowId, int workflowVersion) {
        return workflowVersionService.lambdaQuery()
                .eq(WorkflowVersion::getWorkflowId, workflowId)
                .eq(WorkflowVersion::getVersion, workflowVersion)
                .one();
    }







    @Override
    public CmdResVo deleteWorkflow(String id, Integer version, String userId) {
        //查询当前使用的话术和版本号是否存在
        //查询版本号对应信息是否存在
        WorkflowVersion workflowVersion = getWorkflowVersion(id, version);
        if (workflowVersion == null) {
            throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
        }
        //删除版本号对应信息
        workflowVersionService.removeById(workflowVersion.getId());
        return new CmdResVo(1, workflowVersion.getId());
    }


    @Override
    public CmdResVo copyWorkflow(WorkflowCopyDTO dto, String userId) {
            Workflow sourceWorkflow = baseMapper.selectById(dto.getSourceId());
            if (sourceWorkflow == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value,EnumRCode.DataNotExist.name);
            }
            Workflow newWorkflow = new Workflow();
            BeanUtils.copyProperties(sourceWorkflow, newWorkflow, "id", "version");
            newWorkflow.setName(dto.getName());
            newWorkflow.setCreatedBy(userId);
        //改用参数中获取的辅助的版本号
        //获取当前版本的配置信息
        WorkflowVersion sourceWorkflowVersion = getWorkflowVersion(dto.getSourceId(), dto.getVersion());
            newWorkflow.setVersion(1);
            int result = baseMapper.insert(newWorkflow);
            //同时创建一个版本号，版本名字为当前时间，版本画布数据为空，版本流程配置为空，版本变更日志为复制
            WorkflowVersion workflowVersion = new WorkflowVersion();
            workflowVersion.setWorkflowId(newWorkflow.getId());
            workflowVersion.setVersion(1);
            workflowVersion.setVersionName(JPubUtils.DTimeToString(new Date()));
        workflowVersion.setVersionDesc(sourceWorkflowVersion.getVersionDesc());
            workflowVersion.setCanvasData(sourceWorkflowVersion.getCanvasData());
            workflowVersion.setWorkflowConfig(sourceWorkflowVersion.getWorkflowConfig());
            workflowVersion.setChangeLog("复制");
            workflowVersionService.save(workflowVersion);
            return new CmdResVo(result, newWorkflow.getId());
    }


    @Override
    public CmdResVo switchVersion(WorkflowSwitchVersionDTO dto, String userId) {
            // 这里应该实现版本切换逻辑
            Workflow workflow = baseMapper.selectById(dto.getId());
            if (workflow == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value,EnumRCode.DataNotExist.name);
            }
            //设置使用那个版本
            workflow.setVersion(dto.getVersion());
            workflow.setUpdatedBy(userId);
            int result = baseMapper.updateById(workflow);
            return new CmdResVo(result, dto.getId());
    }


    @Override
    public WorkflowVO getWorkflowDetail(WorkflowDetailDTO workflowDetailDTO) {
           //这里应该查询当前话术使用的模本进行取画布数据
        // 要返回当前版本的信息，是否启用，是否发布，是否上架
        Workflow workflow = baseMapper.selectById(workflowDetailDTO.getWorkflowId());
            if (workflow == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value,EnumRCode.DataNotExist.name);
            }
            //查询当前版本号的版本数据，画布存在这里面
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                    .eq(WorkflowVersion::getWorkflowId, workflowDetailDTO.getWorkflowId())
                        .eq(WorkflowVersion::getVersion, workflow.getVersion())
                        .one();
            WorkflowVO vo = new WorkflowVO();
            BeanUtils.copyProperties(workflow, vo);
            vo.setCanvasData(workflowVersion.getCanvasData());
            vo.setWorkflowConfig(workflowVersion.getWorkflowConfig());
        vo.setAuditStatus(workflowVersion.getAuditStatus());
        vo.setEnableStatus(workflowVersion.getEnableStatus());
        vo.setCurrentVersion(workflowVersion.getVersion());
        vo.setShelfStatus(workflowVersion.getIsShelved());
        vo.setPublishStatus(workflowVersion.getIsPublished());
            return vo;
    }
    @Override
    public IPage<WorkflowVO> getWorkflowList(WorkflowQueryDTO dto) {
        //需要关联版本表，查看当前版本的上架，发布，启动状态
        return selectJoinListPage(new Page<>(dto.getPageNum(), dto.getPageSize()),
                WorkflowVO.class,
                new MPJLambdaWrapper<Workflow>()
                        .leftJoin(WorkflowVersion.class, (wrapper) -> wrapper
                                .eq(WorkflowVersion::getWorkflowId, Workflow::getId)
                                .eq(WorkflowVersion::getVersion, Workflow::getVersion))
                        .selectAll(Workflow.class)
                        .selectAs(Workflow::getVersion, WorkflowVO::getCurrentVersion)
                        .selectAs(WorkflowVersion::getIsShelved, WorkflowVO::getShelfStatus)
                        .selectAs(WorkflowVersion::getIsPublished, WorkflowVO::getPublishStatus)
                        .selectAs(WorkflowVersion::getEnableStatus, WorkflowVO::getEnableStatus)
                        .selectAs(WorkflowVersion::getAuditStatus, WorkflowVO::getAuditStatus)
                        .like(JPubUtils.IsNotEmpty(dto.getName()), Workflow::getName, dto.getName())
                        .eq(JPubUtils.IsNotEmpty(dto.getAuditStatus()), WorkflowVersion::getAuditStatus, dto.getAuditStatus())
                        .eq(JPubUtils.IsNotEmpty(dto.getShelfStatus()), WorkflowVersion::getIsShelved, dto.getShelfStatus())
                        .eq(JPubUtils.IsNotEmpty(dto.getEnableStatus()), WorkflowVersion::getEnableStatus, dto.getEnableStatus())
                        .eq(JPubUtils.IsNotEmpty(dto.getReleaseStatus()), WorkflowVersion::getIsPublished, dto.getReleaseStatus())
                        .eq(JPubUtils.IsNotEmpty(dto.getIndustryType()), Workflow::getIndustryType, dto.getIndustryType())
                        .between(JPubUtils.IsNotEmpty(dto.getStartTime()), WorkflowVersion::getCreatedTime, dto.getStartTime(), dto.getEndTime())
                        .orderByDesc(WorkflowVersion::getCreatedTime)
        );

    }

    @Override
    public List<WorkflowVersionVO> getUserWorkflowVersions(String workflowId, String userId) {
        Workflow workflow = this.getById(workflowId);
        if (workflow == null) {
            throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
        }
        int currentVersion = workflow.getVersion();
       return workflowVersionService.lambdaQuery()
                .eq(WorkflowVersion::getWorkflowId, workflowId)
                .orderByDesc(WorkflowVersion::getVersion)
                .list()
                .stream()
                .map(record -> {
                    WorkflowVersionVO vo = new WorkflowVersionVO();
                    BeanUtils.copyProperties(record, vo);
                    vo.setIsCurrent(record.getVersion() == currentVersion ? 1 : 0);
                    vo.setIsShelved(Objects.equals(record.getIsShelved(), WorkflowStatusEnum.SHELVED.getCode()) ? 1 : 0);
                    vo.setIsPublished(Objects.equals(record.getIsPublished(), WorkflowStatusEnum.PUBLISHED.getCode()) ? 1 : 0);
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public CmdResVo editWorkflowVersion(WorkflowVersionUpdateDTO workflowVersionUpdateDTO, String userId) {
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                        .eq(WorkflowVersion::getId, workflowVersionUpdateDTO.getId())
                        .one();
            if (workflowVersion == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value,EnumRCode.DataNotExist.name);
            }
            BeanUtils.copyProperties(workflowVersionUpdateDTO, workflowVersion);
            workflowVersion.setUpdatedBy(userId);
             workflowVersionService.saveOrUpdate(workflowVersion);
             return new CmdResVo(1, workflowVersionUpdateDTO.getId());
    }

    @Override
    public IPage<WorkflowVO> getUserWorkflows(String userId) {
        return selectJoinListPage(new Page<>(1, 10),
                WorkflowVO.class,
                new MPJLambdaWrapper<Workflow>()
                        .selectAll(Workflow.class)
                        .eq(Workflow::getCreatedBy, userId)
                        .orderByDesc(Workflow::getCreatedTime)
        );
    }

    @Override
    public IPage<WorkflowDetailsVO> getWorkflowDetailsList(WorkflowQueryDTO query) {
        //关联版本表，展示版本的表的所有信息，可根据状态筛选
        return selectJoinListPage(new Page<>(query.getPageNum(), query.getPageSize()),
                WorkflowDetailsVO.class,
                new MPJLambdaWrapper<Workflow>()
                        .leftJoin(WorkflowVersion.class, (wrapper) -> wrapper
                                .eq(WorkflowVersion::getWorkflowId, Workflow::getId))
                        .selectAll(WorkflowVersion.class)
                        .selectAs(Workflow::getName, WorkflowDetailsVO::getName)
                        .selectAs(Workflow::getDescription, WorkflowDetailsVO::getDescription)
                        //状态筛选
                        .eq(JPubUtils.IsNotEmpty(query.getAuditStatus()), WorkflowVersion::getAuditStatus, query.getAuditStatus())
                        .eq(JPubUtils.IsNotEmpty(query.getShelfStatus()), WorkflowVersion::getIsShelved, query.getShelfStatus())
                        .eq(JPubUtils.IsNotEmpty(query.getEnableStatus()), WorkflowVersion::getEnableStatus, query.getEnableStatus())
                        .eq(JPubUtils.IsNotEmpty(query.getReleaseStatus()), WorkflowVersion::getIsPublished, query.getReleaseStatus())
                        //创建时间筛
                        .between(JPubUtils.IsNotEmpty(query.getStartTime()), WorkflowVersion::getCreatedTime, query.getStartTime(), query.getEndTime())
                        .orderByDesc(WorkflowVersion::getCreatedTime)
        );
    }

    @Override
    public CmdResVo changeWorkflowStatus(WorkflowStatusChangeDTO statusChangeDTO, String userId) {
        String workflowId = statusChangeDTO.getWorkflowId();
        Integer version = statusChangeDTO.getVersion();
        Integer enableStatus = statusChangeDTO.getEnableStatus();//是否启用
        Integer releaseStatus = statusChangeDTO.getReleaseStatus();//是否发布（上下线的处理，下线才可以编辑）

        //接下来按照workfolwid 和 version进   进行状态的变更
        //1.如果是启用或者停止状态，则需要判断当前状态是否是已启动或者已停止
        //还需要与任务管理模块进行关联  todo
        //1.1 如何有任务关联正在使用中，不能停止
        if (JPubUtils.IsNotEmpty(enableStatus)) {
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                    .eq(WorkflowVersion::getWorkflowId, workflowId)
                    .eq(WorkflowVersion::getVersion, version)
                    .one();
            if (workflowVersion == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
            }
            workflowVersion.setEnableStatus(enableStatus);
            workflowVersionService.saveOrUpdate(workflowVersion);
        }
        //1.2 改为已启动状态
        if (JPubUtils.IsNotEmpty(enableStatus) && enableStatus.equals(WorkflowStatusEnum.ENABLED.getCode())) {
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                    .eq(WorkflowVersion::getWorkflowId, workflowId)
                    .eq(WorkflowVersion::getVersion, version)
                    .one();
            if (workflowVersion == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
            }
            workflowVersion.setEnableStatus(enableStatus);
            workflowVersionService.saveOrUpdate(workflowVersion);
        }

        //2.如果是发布或者取消发布状态
        //2.1 改为未发布状态,未发布状态才可以编辑
        if (JPubUtils.IsNotEmpty(releaseStatus) && releaseStatus.equals(WorkflowStatusEnum.NOT_PUBLISHED.getCode())) {
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                    .eq(WorkflowVersion::getWorkflowId, workflowId)
                    .eq(WorkflowVersion::getVersion, version)
                    .one();
            if (workflowVersion == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
            }
            workflowVersion.setEnableStatus(releaseStatus);
            workflowVersionService.saveOrUpdate(workflowVersion);
        }
        //2.2 改为已发布状态，这里需要走审批  todo
        if (JPubUtils.IsNotEmpty(releaseStatus) && releaseStatus.equals(WorkflowStatusEnum.PUBLISHED.getCode())) {
            WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                    .eq(WorkflowVersion::getWorkflowId, workflowId)
                    .eq(WorkflowVersion::getVersion, version)
                    .one();
            if (workflowVersion == null) {
                throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
            }
            //1.先设置审核状态，审核中
            workflowVersion.setAuditStatus(WorkflowStatusEnum.AUDIT_REVIEWING.getCode());
            //2.向审批表插入数据，记录谁审批的  todo


            //3.审批完成后申请的版本表记录一下审核状态   todo


            workflowVersionService.saveOrUpdate(workflowVersion);
        }
        return new CmdResVo(1, workflowId);
    }

    @Override
    public CmdResVo withdrawWorkflow(WorkflowWithdrawDTO workflowWithdrawDTO, String userId) {
        //1.将要撤回的版本设置为未发布
        String workflowId = workflowWithdrawDTO.getWorkflowId();
        Integer version = workflowWithdrawDTO.getVersion();
        WorkflowVersion workflowVersion = workflowVersionService.lambdaQuery()
                .eq(WorkflowVersion::getWorkflowId, workflowId)
                .eq(WorkflowVersion::getVersion, version)
                .one();
        if (workflowVersion == null) {
            throw new ServiceException(EnumRCode.DataNotExist.value, EnumRCode.DataNotExist.name);
        }
        //1.设置审核状态为待审核
        workflowVersion.setAuditStatus(WorkflowStatusEnum.AUDIT_PENDING.getCode());


        //2.审核记录表中要删除


        //3.原先发布表的记录要删除


        return null;
    }
}




